﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DcsGauges.Gui.Rendering;
using DcsGauges.Gui.Gauges.Interfaces;
using DcsGauges.DataStructures;
using Microsoft.Xna.Framework.Graphics;
using DcsGauges.Shared.DataStructures;
using Microsoft.Xna.Framework;

namespace DcsGauges.Gui.Gauges.Panels
{
    using Cp = DcsProperties.Panels.Right.Caution;
using DcsGauges.Gui.Gauges.ValueConverters;

    internal class CautionPanel : GuiRenderableBase, IMultiValueGauge
    {
        #region Readonly & Constants

        private const           int                                     CAUTION_ROWS                        = 12;
        private const           int                                     CAUTION_COLS                        = 4;

        private static readonly IGaugeValueConverter<float, bool>       CONVERTER                           = new BoolConverter(0.5f);

        private readonly  DcsProperty[,]            PROPS                               = 
        {
            { Cp.EngineStartCycle,                  Cp.HydraulicPressLeft,                  Cp.HydraulicPressRight,                         Cp.GunUnsafe            },
            { Cp.AntiSkid,                          Cp.HydraulicResLeft,                    Cp.HydraulicResRight,                           Cp.OxygenLow            },
            { Cp.ElevationDisengage,                Cp.Space1,                              Cp.SeatNotArmed,                                Cp.BleedAirLeak         },
            { Cp.AilDisengage,                      Cp.AilTabLeft,                          Cp.AilTabRight,                                 Cp.ServiceAirHot        },
            { Cp.PitchSas,                          Cp.EngineHotLeft,                       Cp.EngineHotRight,                              Cp.WindShieldHot        },
            { Cp.YawSas,                            Cp.EngineOilPressLeft,                  Cp.EngineOilPressRight,                         Cp.Cicu                 },
            { Cp.Gcas,                              Cp.MainPumpLeft,                        Cp.MainPumpRight,                               Cp.Space2               },
            { Cp.Laste,                             Cp.WingPumpLeft,                        Cp.WingPumpRight,                               Cp.Hars                 },
            { Cp.IffMode4,                          Cp.MainFuelLowLeft,                     Cp.MainFuelLowRight,                            Cp.LeftRightTanksUnequal},
            { Cp.Eac,                               Cp.FuelPressLeft,                       Cp.FuelPressRight,                              Cp.Nav                  },
            { Cp.StallSystem,                       Cp.ConvLeft,                            Cp.ConvRight,                                   Cp.Cadc                 },
            { Cp.ApuGen,                            Cp.GeneratorLeft,                       Cp.GeneratorRight,                              Cp.InstInverter         },
        };

        #endregion


        #region Fields & Properties

        private Texture2D                           backgroundTex                       = null;
        private Texture2D                           foregroundTex                       = null;
        
        private Dictionary<DcsProperty, Rectangle>  sourceTextCoords                    = new Dictionary<DcsProperty, Rectangle>();
        private Dictionary<DcsProperty, URect>      destinationRects                    = new Dictionary<DcsProperty, URect>();
        private Dictionary<DcsProperty, float>      propertyValues                      = new Dictionary<DcsProperty, float>();

        #endregion


        #region Constructors

        public CautionPanel(GuiRenderableBase parent, URect area) : base(parent, area)
        {
            this.backgroundTex              = TextureManager.GetTexture(ClientConstants.Textures.Panels.Back.Caution);
            this.foregroundTex              = TextureManager.GetTexture(ClientConstants.Textures.Panels.Fore.CuationText);

            for(int col = 0; col < CAUTION_COLS; col++)
            {
                for(int row = 0; row < CAUTION_ROWS; row++)
                {
                    DcsProperty prop                                = PROPS[row, col];
                    this.properties[row * CAUTION_COLS + col]       = prop;
                    this.sourceTextCoords[prop]                     = this.CalcTexturePart(row, col, this.foregroundTex);
                    this.destinationRects[prop]                     = new URect(new ULoc(col * 1.0f / (float)CAUTION_COLS, row * 1.0f / (float)CAUTION_ROWS), 
                        new USize(1.0f / (float)CAUTION_COLS, 1.0f / (float)CAUTION_ROWS));
                    this.propertyValues[prop]                       = 1.0f;
                }
            }
        }

        #endregion


        #region Interface Implementation

        private DcsProperty[] properties            = new DcsProperty[CAUTION_ROWS * CAUTION_COLS];
        public DcsProperty[] Properties
        {
            get { return this.properties; }
        }

        public void SetValue(DcsProperty property, float value)
        {
            //this.propertyValues[property] = value;
        }

        public float GetValue(DcsProperty property)
        {
            return this.properties[property];
        }

        #endregion


        #region Overrides

        public override void Render(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, Microsoft.Xna.Framework.Graphics.GraphicsDevice device, Microsoft.Xna.Framework.Rectangle parentRect, float globalZIndex)
        {
            Rectangle? origianlDim              = base.keepAspectRatio ? this.backgroundTex.Bounds : new Rectangle?();
            Rectangle viewportRect              = base.CalcViewportRect(parentRect, origianlDim);

            spriteBatch.Draw(this.backgroundTex, viewportRect, null, Color.White, 0.0f, Vector2.Zero, SpriteEffects.None, base.NextFrontIndex(globalZIndex, 1));

            for(int i = 0; i < this.properties.Length; i++)
            {
                var prop            = this.properties[i];

                if(prop == null)
                {
                    continue;
                }

                bool cautionIsLit   = CONVERTER.Convert(this.propertyValues[prop]);

                if(cautionIsLit)
                {
                    Rectangle dest = base.CalcViewportRect(this.destinationRects[prop], viewportRect);
                    spriteBatch.Draw(this.foregroundTex, dest, this.sourceTextCoords[prop], Color.White, 0.0f, Vector2.Zero, SpriteEffects.None, base.NextFrontIndex(globalZIndex, 2));
                }
            }
        }

        #endregion


        #region Helpers & Internals

        private Rectangle CalcTexturePart(int row, int col, Texture2D tex)
        {
            int dx              = tex.Width / CAUTION_COLS;
            int dy              = tex.Height / CAUTION_ROWS;

            int x1              = dx * col;
            int y1              = dy * row;
            
            return new Rectangle(x1, y1, dx, dy);
        }

        #endregion
    }
}
